package com.zuo;

import java.security.PublicKey;

public class EnumClass {
    public static void main(String[] args) {
//        使用常量的时候,可以这么引用
        int day = 3;
        if (day == Weekday.SAT || day == Weekday.SUN) {
            System.out.println("work at home");
        } else {
            System.out.println("work at company");
        }

//        使用字符串的常量
        String color = "r";
        if (Color.RED.equals(color)) {
            System.out.println("红色");
        } else if (Color.BLUE.equals(color)) {
            System.out.println("蓝色");
        } else if (Color.GREEN.equals(color)) {
            System.out.println("绿色");
        }

//       无论是int常量还是String常量，使用这些常量来表示一组枚举值的时候，有一个严重的问题就是，编译器无法检查每个值的合理性

//        1:为了让编译器能自动检查某个值在枚举的集合内，并且，不同用途的枚举需要不同的类型来标记，不能混用，我们可以使用enum来定义枚举类：

        Weekday1 day1 = Weekday1.SUN;
        if (day1 == Weekday1.SAT || day1 == Weekday1.SUN) {
            System.out.println("work at home");
        } else {
            System.out.println("work at office");
        }
//       定义枚举类是通过关键字enum实现的，我们只需依次列出枚举的常量名。
//       和int定义的常量相比，使用enum定义枚举有如下好处：
//       首先，enum常量本身带有类型信息，即Weekday1.SUN类型是Weekday1，编译器会自动检查出类型错误
//       其次，不可能引用到非枚举的值，因为无法通过编译。
//       最后，不同类型的枚举不能互相比较或者赋值，因为类型不符。例如，不能给一个Weekday枚举类型的变量赋值为Color枚举类型的值
        int day2 = 1;
//        if (day2 == Weekday1.SUN) {
//
//        }
        // Compile error: bad operand types for binary operator '=='

        Weekday1 day3 = Weekday1.SUN;
//        Weekday1 day4 = Color.RED;// Compile error: incompatible types

//        2:enum的比较
//        使用enum定义的枚举类是一种引用类型。前面我们讲到，引用类型比较，要使用equals()方法，如果使用==比较，它比较的是两个引用类型的变量是否是同一个对象。因此，引用类型比较，要始终使用equals()方法，但enum类型可以例外。
//        这是因为enum类型的每个常量在JVM中只有一个唯一实例，所以可以直接用==比较：
        if (day3 == Weekday1.FRI){

        }
        if (day3.equals(Weekday1.SUN)){

        }

//        3:enum类型
//        通过enum定义的枚举类,和其他class有什么区别
//        答案是没有任何区别,enum定义的类型就是class，只不过它有以下几个特点：
/*
* 定义的enum类型总是继承自java.lang.Enum，且无法被继承；
* 只能定义出enum的实例，而无法通过new操作符创建enum的实例；
* 定义的每个实例都是引用类型的唯一实例；
* 可以将enum类型用于switch语句。
* */

//        4:name(),返回枚举常量名
        String s = day3.name();
        System.out.println("day3的常量名是: " + s);

//        5:ordinal(),返回定义常量时的顺序,从0开始计数
//        改变枚举常量定义的顺序就会到值ordianl()返回值发生改变
        int n = day3.ordinal();
        System.out.println("day3的顺序是: " + n);

//        6:默认情况下，对枚举常量调用toString()会返回和name()一样的字符串。但是，toString()可以被覆写，而name()则不行。我们可以给Weekday添加toString()方法：
        Weekday3 day4 = Weekday3.THU;
        if (day4.dayValue == 6 || day4.dayValue == 7){
            System.out.println("Today is " + day4.toString() + ".Work at home");
        }else{
            System.out.println("Today is " + day4.toString() + ".Work at office");
        }

//        7:switch
//        枚举值可以应用在switch语句中,因为枚举类天生具有类型信息和有限个枚举常量，所以比int、String类型更适合用在switch语句中：
        Weekday3 day5 = Weekday3.SUN;
        switch (day5){
            case MON:
            case TUE:
            case WED:
            case THU:
            case FRI:
                System.out.println("Today is " + day5 + ".Work at office!");
                break;
            case SAT:
            case SUN:
                System.out.println("Today is " + day5 + ".Work at home!");
                break;
            default:
                throw new RuntimeException("cannot process " + day5);
//                加上default语句，可以在漏写某个枚举常量时自动报错，从而及时发现错误。
        }
    }

}

class Weekday {
    public static final int SUN = 0;
    public static final int MON = 1;
    public static final int TUE = 2;
    public static final int WED = 3;
    public static final int THU = 4;
    public static final int FRI = 5;
    public static final int SAT = 6;
}

class Color {
    public static final String RED = "r";
    public static final String GREEN = "g";
    public static final String BLUE = "b";

}

//定义星期枚举类
enum Weekday1 {
    SUN, MON, TUE, WED, THU, FRI, SAT;
}

//给枚举常量添加字段,定义private的构造方法
enum  Weekday2 {
    MON(1),
    TUE(2),
    WED(3),
    THU(4),
    FRI(5),
    SAT(6),
    SUN(0);


    public final int dayValue;
    private Weekday2(int dayValue) {
        this.dayValue = dayValue;
    }
}

//给枚举常量添加dayValue和chinese字段,定义private的构造方法,覆写toString()方法
enum Weekday3 {

    MON(1,"星期一"),
    TUE(2,"星期二"),
    WED(3,"星期三"),
    THU(4,"星期四"),
    FRI(5,"星期五"),
    SAT(6,"星期六"),
    SUN(7,"星期日");

    public final int dayValue;
    private final String chinese;

    private Weekday3(int dayValue,String chinese){
        this.dayValue = dayValue;
        this.chinese = chinese;
    }

//    可以覆写toString方法,返回自己想要的值
    @Override
    public String toString(){
        return this.chinese;
    }
}

